home *** CD-ROM | disk | FTP | other *** search
/ Aminet 51 / Aminet 51 (2002)(GTI - Schatztruhe)[!][Oct 2002].iso / Aminet / dev / src / xad_bzip.lha / bzip.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-18  |  16.5 KB  |  647 lines

  1. /* bzip -- an XAD client for extracting bzip (not bzip2) files
  2.  * This XAD client is (C) 2000-2002 Stuart Caie <kyzer@4u.net>, but the
  3.  * original bzip decompression code used in this client was written by
  4.  * bzip's author, Julian Seward. bzip is (C) 1996 Julian R. Seward.
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /* $VER: bzip.c 1.2 (17.08.2002) */
  22.  
  23. #include <libraries/xadmaster.h>
  24. #include <proto/xadmaster.h>
  25. #include <string.h>
  26. #include "SDI_compiler.h"
  27.  
  28. #ifdef DEBUG
  29. void KPrintF(char *fmt, ...);
  30. #define D(x) { KPrintF x ; }
  31. #else
  32. #define D(x)
  33. #endif
  34.  
  35. #define XADBASE  REG(a6, struct xadMasterBase *xadMasterBase)
  36.  
  37. #ifndef XADMASTERFILE
  38. #define bzip_Client     FirstClient
  39. #define NEXTCLIENT      0
  40. const UBYTE version[] = "$VER: bzip 1.2 (17.08.2002)";
  41. #endif
  42. #define BZIP_VERSION    1
  43. #define BZIP_REVISION   2
  44.  
  45.  
  46. ASM(BOOL) bzip_RecogData(REG(d0, ULONG size), REG(a0, STRPTR data), XADBASE) {
  47.   if (data[0] != 'B' || data[1] != 'Z' || data[2] != '0') return 0;
  48.   if (data[3] <  '1' || data[3] > '9') return 0;
  49.   return 1;
  50. }
  51.  
  52. /* there's only one file in a bzip archive - the uncompressed data */
  53. ASM(LONG) bzip_GetInfo(REG(a0, struct xadArchiveInfo *ai), XADBASE) {
  54.   struct TagItem tags[]  = {
  55.     { XAD_OBJNAMESIZE, 0 },
  56.     { TAG_DONE, 0 }
  57.   };
  58.  
  59.   struct TagItem datetags[] = {
  60.     { XAD_DATECURRENTTIME, 1 },
  61.     { XAD_GETDATEXADDATE,  0 },
  62.     { TAG_DONE, 0 }
  63.   };
  64.  
  65.   struct xadFileInfo *fi;
  66.   char *name;
  67.   int namelen;
  68.  
  69.   /* do we have a filename for this archive? */
  70.   if ((name = ai->xai_InName))
  71.     tags[0].ti_Data = namelen = strlen(name) + 1;
  72.  
  73.   if (!(ai->xai_FileInfo = fi = (struct xadFileInfo *) xadAllocObjectA(
  74.     XADOBJ_FILEINFO, (name) ? tags : NULL))) return XADERR_NOMEMORY;
  75.   fi->xfi_EntryNumber = 1;
  76.   fi->xfi_CrunchSize  = ai->xai_InSize - 4;
  77.   fi->xfi_Size        = 0;
  78.   fi->xfi_DataPos     = 3;
  79.   fi->xfi_Flags = XADFIF_NODATE | XADFIF_NOUNCRUNCHSIZE | XADFIF_SEEKDATAPOS;
  80.  
  81.   /* fill in today's date */
  82.   datetags[1].ti_Data = (ULONG) &fi->xfi_Date;
  83.   xadConvertDatesA(datetags);
  84.  
  85.   if (name) {
  86.     xadCopyMem(ai->xai_InName, (name = fi->xfi_FileName), namelen);
  87.     if (name[namelen-4] == '.'
  88.     && (name[namelen-3] == 'b' || name[namelen-3] == 'B')
  89.     && (name[namelen-2] == 'z' || name[namelen-2] == 'Z'))
  90.       name[namelen-4] = 0;
  91.   }
  92.   else {
  93.     fi->xfi_FileName = xadMasterBase->xmb_DefaultName;
  94.     fi->xfi_Flags   |= XADFIF_NOFILENAME;
  95.   }
  96.   return XADERR_OK;
  97. }
  98.  
  99.  
  100.  
  101. /* here begins the hard bit */
  102.  
  103. #define BZIP_READBUF_SIZE  512
  104. #define BZIP_OUTBUF_SIZE   4096
  105. #define BZIP_MAX_SYMBOLS   256
  106.  
  107. typedef 
  108.    struct {
  109.       ULONG  numScalings;
  110.       ULONG  numTraffic;
  111.       ULONG  totFreq;
  112.       ULONG  numSymbols;
  113.       ULONG  incValue;
  114.       ULONG  noExceed;
  115.       ULONG  freq[BZIP_MAX_SYMBOLS + 2];
  116.    }
  117.    Model;
  118.  
  119. struct BZIPstate {
  120.   struct xadMasterBase *xad;
  121.   struct xadArchiveInfo *ai;
  122.  
  123.   Model models[8], bogusModel;
  124.   ULONG bigL, bigR, bigD;
  125.  
  126.   UBYTE readbuf[BZIP_READBUF_SIZE], *bufp, *bufend;
  127.   UBYTE outbuf[BZIP_OUTBUF_SIZE], *obufp, *obufend;
  128.   ULONG bitbuf;
  129.   UBYTE bitsleft;
  130.  
  131.   ULONG blocklen;      /* length of block */
  132.   UBYTE err;           /* error code */
  133.   UBYTE lastblock;     /* flag - is this the last block? */
  134.   ULONG crc;           /* CRC-so-far */
  135.   LONG  last;
  136.   LONG  origPtr;
  137.  
  138.   /* big memory areas */
  139.   UBYTE *block, *ll;
  140.   LONG *zptr;
  141. };
  142.  
  143. static void bzip_fill_readbuf(struct BZIPstate *bzs) {
  144.   struct xadMasterBase *xadMasterBase = bzs->xad;
  145.   struct xadArchiveInfo *ai = bzs->ai;
  146.   ULONG avail = ai->xai_InSize - ai->xai_InPos;
  147.  
  148.   if (avail > BZIP_READBUF_SIZE) avail = BZIP_READBUF_SIZE;
  149.   bzs->bufend = (bzs->bufp = bzs->readbuf) + avail;
  150.   bzs->err = xadHookAccess(XADAC_READ, avail, (APTR)&bzs->readbuf, ai);
  151. }
  152.  
  153. #define ULONG_BITS (sizeof(ULONG)<<3)
  154. #define ENSURE_BITS(n) while (bzs->bitsleft < (n)) { \
  155.   if (bzs->bufp >= bzs->bufend) bzip_fill_readbuf(bzs); \
  156.   bzs->bitbuf |= *bzs->bufp++ << (ULONG_BITS-8 - bzs->bitsleft); \
  157.   bzs->bitsleft += 8; \
  158. }
  159. #define PEEK_BITS(n)   (bzs->bitbuf >> (ULONG_BITS - (n)))
  160. #define REMOVE_BITS(n) ((bzs->bitbuf <<= (n)), (bzs->bitsleft -= (n)))
  161. #define READ_BITS(v,n) {ENSURE_BITS(n); (v)=PEEK_BITS(n); REMOVE_BITS(n);}
  162.  
  163. static ULONG bzip_crc32Table[256];
  164.  
  165. #define TWO_TO_THE(n)        (1 << (n))
  166. #define MAX_BITS_OUTSTANDING 500000000
  167.  
  168. #define smallB 26
  169. #define smallF 18
  170.  
  171. #define BASIS           0
  172. #define MODEL_2_3       1
  173. #define MODEL_4_7       2
  174. #define MODEL_8_15      3
  175. #define MODEL_16_31     4
  176. #define MODEL_32_63     5
  177. #define MODEL_64_127    6
  178. #define MODEL_128_255   7
  179.  
  180. static void bzip_arithCodeStartDecoding (struct BZIPstate *bzs) {
  181.   bzs->bigL = 0;
  182.   bzs->bigR = TWO_TO_THE(smallB-1);
  183.   bzs->bigD = 0;
  184.   READ_BITS(bzs->bigD, smallB);
  185. }
  186.  
  187. static LONG bzip_arithDecodeSymbol(struct BZIPstate *bzs, Model *m) {
  188.   ULONG smallL, smallH, smallT, smallR;
  189.   ULONG smallR_x_smallL, target, symbol;
  190.   ULONG bits, mybits;
  191.  
  192.   smallT = m->totFreq;
  193.  
  194.   /*--- Get target value. ---*/
  195.   if (smallT == 0) {
  196.     D(("smallT == 0\n"))
  197.     bzs->err = XADERR_ILLEGALDATA;
  198.     return -1;
  199.   }
  200.   smallR = bzs->bigR / smallT;
  201.  
  202.   if (smallR == 0) {
  203.     D(("smallR == 0\n"))
  204.     bzs->err = XADERR_ILLEGALDATA;
  205.     return -1;
  206.   }
  207.   target = bzs->bigD / smallR;
  208.  
  209.   if ((smallT-1) < target) target = smallT-1;
  210.  
  211.   symbol = 0;
  212.   smallH = 0;
  213.   while (smallH <= target) {
  214.     symbol++;
  215.     smallH += m->freq[symbol];
  216.   }
  217.   smallL = smallH - m->freq[symbol];
  218.  
  219.   smallR_x_smallL = smallR * smallL;
  220.   bzs->bigD -= smallR_x_smallL;
  221.    
  222.   if (smallH < smallT)
  223.     bzs->bigR = smallR * (smallH - smallL);
  224.   else
  225.     bzs->bigR -= smallR_x_smallL;
  226.  
  227.   bits=0;
  228.   while ( bzs->bigR <= TWO_TO_THE ( smallB-2 ) ) {
  229.     bzs->bigR <<= 1; bits++;
  230.   }
  231.   bzs->bigD <<= bits;
  232.   READ_BITS(mybits, bits);
  233.   bzs->bigD |= mybits;
  234.   return (LONG)symbol;
  235. }
  236.  
  237. static void bzip_initModel(
  238.   Model *m,
  239.   LONG initNumSymbols,
  240.   LONG initIncValue,
  241.   LONG initNoExceed
  242. ) {
  243.  
  244.   LONG i;
  245.   if (initIncValue == 0) {
  246.     m->totFreq = initNumSymbols;
  247.     for (i = 1; i <= initNumSymbols; i++) 
  248.       m->freq[i] = 1;
  249.   } else {
  250.     m->totFreq = initNumSymbols * initIncValue;
  251.     for (i = 1; i <= initNumSymbols; i++) 
  252.       m->freq[i] = initIncValue;
  253.   };
  254.  
  255.   m->numSymbols                = initNumSymbols;
  256.   m->incValue                  = initIncValue;
  257.   m->noExceed                  = initNoExceed;
  258.   m->freq[0]                   = 0;
  259.   m->freq[initNumSymbols + 1]  = 0;
  260.   m->numScalings               = 0;
  261. }
  262.  
  263.  
  264. static void bzip_updateModel(Model *m, LONG symbol) {
  265.   ULONG i;
  266.   m->totFreq      += m->incValue;
  267.   m->freq[symbol] += m->incValue;
  268.   if (m->totFreq > m->noExceed) {
  269.     m->totFreq = 0;
  270.     m->numScalings++;
  271.     for (i = 1; i <= m->numSymbols; i++) {
  272.       m->freq[i] = (m->freq[i] + 1) >> 1;
  273.       m->totFreq += m->freq[i];
  274.     }
  275.   }
  276. }
  277.  
  278. static INLINE LONG bzip_getSymbol(struct BZIPstate *bzs, Model *m) {
  279.   LONG symbol;
  280.   if (bzs->err) return -1;
  281.   symbol = bzip_arithDecodeSymbol(bzs, m);
  282.   if (bzs->err) return -1;
  283.   bzip_updateModel(m, symbol);
  284.   return symbol;
  285. }
  286.  
  287. static void bzip_initBogusModel(struct BZIPstate *bzs) {
  288.   bzip_initModel(&bzs->bogusModel, 256, 0, 256);
  289. }
  290.  
  291. static INLINE UBYTE bzip_getUBYTE(struct BZIPstate *bzs) {
  292.   return (UBYTE) (bzip_getSymbol(bzs, &bzs->bogusModel) - 1);
  293. }
  294.  
  295.  
  296. static INLINE LONG bzip_getLONG(struct BZIPstate *bzs) {
  297.   ULONG x =
  298.      (bzip_getUBYTE(bzs) << 24)
  299.    | (bzip_getUBYTE(bzs) << 16)
  300.    | (bzip_getUBYTE(bzs) <<  8)
  301.    | (bzip_getUBYTE(bzs)      );
  302.   return (LONG) x;
  303. }
  304.  
  305. static INLINE ULONG bzip_getULONG(struct BZIPstate *bzs) {
  306.   return
  307.      (bzip_getUBYTE(bzs) << 24)
  308.    | (bzip_getUBYTE(bzs) << 16)
  309.    | (bzip_getUBYTE(bzs) <<  8)
  310.    | (bzip_getUBYTE(bzs)      );
  311. }
  312.  
  313.  
  314. static void bzip_initModels(struct BZIPstate *bzs) {
  315.   bzip_initModel(&bzs->models[BASIS],         11,  12,  1000);
  316.   bzip_initModel(&bzs->models[MODEL_2_3],     2,   4,   1000);
  317.   bzip_initModel(&bzs->models[MODEL_4_7],     4,   3,   1000);
  318.   bzip_initModel(&bzs->models[MODEL_8_15],    8,   3,   1000);
  319.   bzip_initModel(&bzs->models[MODEL_16_31],   16,  3,   1000);
  320.   bzip_initModel(&bzs->models[MODEL_32_63],   32,  3,   1000);
  321.   bzip_initModel(&bzs->models[MODEL_64_127],  64,  2,   1000);
  322.   bzip_initModel(&bzs->models[MODEL_128_255], 128, 1,   1000);
  323. }
  324.  
  325.  
  326. #define VAL_RUNA     1
  327. #define VAL_RUNB     2
  328. #define VAL_ONE      3
  329. #define VAL_2_3      4
  330. #define VAL_4_7      5
  331. #define VAL_8_15     6
  332. #define VAL_16_31    7
  333. #define VAL_32_63    8
  334. #define VAL_64_127   9
  335. #define VAL_128_255  10
  336. #define VAL_EOB      11
  337.  
  338. #define RUNA    257
  339. #define RUNB    258
  340. #define EOB     259
  341. #define INVALID 260
  342.  
  343. static INLINE LONG bzip_getMTFVal(struct BZIPstate *bzs) {
  344.   switch (bzip_getSymbol(bzs, &bzs->models[BASIS])) {
  345.   case VAL_EOB:    return EOB;
  346.   case VAL_RUNA:   return RUNA;
  347.   case VAL_RUNB:   return RUNB;
  348.   case VAL_ONE:    return 1;
  349.   case VAL_2_3:    return bzip_getSymbol(bzs, &bzs->models[MODEL_2_3])+2-1;
  350.   case VAL_4_7:    return bzip_getSymbol(bzs, &bzs->models[MODEL_4_7])+4-1;
  351.   case VAL_8_15:   return bzip_getSymbol(bzs, &bzs->models[MODEL_8_15])+8-1;
  352.   case VAL_16_31:  return bzip_getSymbol(bzs, &bzs->models[MODEL_16_31])+16-1;
  353.   case VAL_32_63:  return bzip_getSymbol(bzs, &bzs->models[MODEL_32_63])+32-1;
  354.   case VAL_64_127: return bzip_getSymbol(bzs, &bzs->models[MODEL_64_127])+64-1;
  355.   }
  356.   return (LONG) bzip_getSymbol(bzs, &bzs->models[MODEL_128_255]) + 128 - 1;
  357. }
  358.  
  359. static void bzip_getAndMoveToFrontDecode(struct BZIPstate *bzs) {
  360.   UBYTE  yy[256];
  361.   LONG  i, j, tmpOrigPtr, nextSym, limit;
  362.  
  363.   limit = bzs->blocklen;
  364.  
  365.   tmpOrigPtr = bzip_getLONG(bzs);
  366.   if (bzs->err) return;
  367.  
  368.   if (tmpOrigPtr < 0) 
  369.     bzs->origPtr = ( -tmpOrigPtr ) - 1;
  370.   else
  371.     bzs->origPtr =    tmpOrigPtr   - 1;
  372.  
  373.   bzip_initModels(bzs);
  374.  
  375.   for (i = 0; i <= 255; i++) {
  376.     yy[i] = (UBYTE) i;
  377.   }
  378.    
  379.   bzs->last = -1;
  380.  
  381.   nextSym = bzip_getMTFVal(bzs);
  382.  
  383.   LOOPSTART:
  384.  
  385.   if (bzs->err) return;
  386.  
  387.   if (nextSym == EOB) { bzs->lastblock = (tmpOrigPtr < 0); return; }
  388.  
  389.   /*--- acquire run-length bits, most significant first ---*/
  390.   if (nextSym == RUNA || nextSym == RUNB) {
  391.     LONG n = 0, bits = 31;
  392.     do {
  393.       if (!--bits) {
  394.         D(("too many bits\n"))
  395.         bzs->err = XADERR_ILLEGALDATA; return;
  396.       }
  397.       
  398.       n <<= 1;
  399.       if (nextSym == RUNA) n |= 1;
  400.       n++;
  401.       nextSym = bzip_getMTFVal(bzs);
  402.       if (bzs->err) return;
  403.     } while (nextSym == RUNA || nextSym == RUNB);
  404.  
  405.     while (n > 0) {
  406.       bzs->last++;
  407.       if (bzs->last >= limit) {
  408.         D(("RLE limits\n"))
  409.         bzs->err = XADERR_OUTPUT; return;
  410.       }
  411.       bzs->ll[bzs->last] = yy[0];
  412.       n--;
  413.     }
  414.     goto LOOPSTART;
  415.   }
  416.  
  417.   if (nextSym >= 1 && nextSym <= 255) {
  418.     bzs->last++;
  419.     if (bzs->last >= limit) {
  420.       D(("limits\n"))
  421.       bzs->err = XADERR_OUTPUT; return;
  422.     }
  423.     bzs->ll[bzs->last] = yy[nextSym];
  424.  
  425.     /*--
  426.        This loop is hammered during decompression,
  427.        hence the unrolling.
  428.  
  429.        for (j = nextSym; j > 0; j--) yy[j] = yy[j-1];
  430.     --*/
  431.  
  432.     j = nextSym;
  433.     for (; j > 3; j -= 4) {
  434.       yy[j]   = yy[j-1]; 
  435.       yy[j-1] = yy[j-2];
  436.       yy[j-2] = yy[j-3];
  437.       yy[j-3] = yy[j-4];
  438.     }
  439.     for (; j > 0; j--) yy[j] = yy[j-1];
  440.  
  441.     yy[0] = bzs->ll[bzs->last];
  442.     nextSym = bzip_getMTFVal(bzs);
  443.     goto LOOPSTART;
  444.   }
  445.  
  446.   bzs->err = XADERR_ILLEGALDATA;
  447.   return;
  448. }
  449.  
  450. static void bzip_undoReversibleTransformation(struct BZIPstate *bzs) {
  451.   UBYTE *block = bzs->block, *ll = bzs->ll;
  452.   LONG  cc[256], *zptr = bzs->zptr;
  453.   LONG  i, j, ch, sum;
  454.  
  455.   for (i = 0; i <= 255; i++) cc[i] = 0;
  456.    
  457.   for (i = 0; i <= bzs->last; i++) {
  458.     UBYTE ll_i = ll[i];
  459.     zptr[i] = cc[ll_i];
  460.     cc[ll_i] ++;
  461.   }
  462.  
  463.   sum = 0;
  464.   for (ch = 0; ch <= 255; ch++) {
  465.     sum = sum + cc[ch];
  466.     cc[ch] = sum - cc[ch];
  467.   }
  468.  
  469.   i = bzs->origPtr;
  470.   for (j = bzs->last; j >= 0; j--) {
  471.     UBYTE ll_i = ll[i];
  472.     block[j] = ll_i;
  473.     i = zptr[i] + cc[ll_i];
  474.   }
  475. }
  476.  
  477. #define SPOT_BASIS_STEP 8000
  478.  
  479. static void bzip_spotBlock (struct BZIPstate *bzs) {
  480.   LONG pos, delta, newdelta;
  481.   UBYTE *block = bzs->block;
  482.  
  483.   pos   = SPOT_BASIS_STEP;
  484.   delta = 1;
  485.  
  486.   while (pos < bzs->last) {
  487.     LONG n = (LONG) block[pos] - 1;
  488.          if (n == 256) n = 0;
  489.     else if (n == -1)  n = 255;
  490.  
  491.     if (n < 0 || n > 255) {
  492.        bzs->err = XADERR_ILLEGALDATA;
  493.        return;
  494.     }
  495.  
  496.     block[pos] = (UBYTE)n;
  497.     switch (delta) {
  498.     case 3:  newdelta = 1; break;
  499.     case 1:  newdelta = 4; break;
  500.     case 4:  newdelta = 5; break;
  501.     case 5:  newdelta = 9; break;
  502.     case 9:  newdelta = 2; break;
  503.     case 2:  newdelta = 6; break;
  504.     case 6:  newdelta = 7; break;
  505.     case 8:  newdelta = 8; break;
  506.     case 7:  newdelta = 3; break;
  507.     default: newdelta = 1; break;
  508.     }
  509.     delta = newdelta;
  510.     pos = pos + SPOT_BASIS_STEP + 17 * (newdelta - 5);
  511.   }
  512.  
  513.  
  514. #define OUTPUT_BYTE(byte) do { \
  515.   if (bzs->obufp >= bzs->obufend) { \
  516.     if ((bzs->err = xadHookAccess(XADAC_WRITE, BZIP_OUTBUF_SIZE, \
  517.     (APTR) bzs->outbuf, ai))) return; \
  518.     bzs->obufp = bzs->outbuf; \
  519.   } \
  520.   *bzs->obufp++ = (byte); \
  521.   crc = (crc<<8) ^ bzip_crc32Table[(crc>>24) ^ ((byte) & 0xFF)]; \
  522. } while(0)
  523.  
  524.  
  525. static void bzip_unRLEandDump(struct BZIPstate *bzs) {
  526.   struct xadMasterBase *xadMasterBase = bzs->xad;
  527.   struct xadArchiveInfo *ai = bzs->ai;
  528.   UBYTE *block = bzs->block;
  529.   ULONG crc = bzs->crc;
  530.  
  531.   LONG  i = 0, j, numbytes = bzs->last, count = 0, chPrev, ch = 256;
  532.   UBYTE c;
  533.  
  534.   if (bzs->lastblock) numbytes--;
  535.  
  536.   while (i <= numbytes) {
  537.     chPrev = ch;
  538.     ch = block[i];
  539.     i++;
  540.  
  541.     c = (UBYTE) ch;
  542.     OUTPUT_BYTE(c);
  543.     if (ch != chPrev) {
  544.       count = 1;
  545.     } else {
  546.       count++;
  547.       if (count >= 4) {
  548.         c = (UBYTE) ch;
  549.         j = block[i];
  550.         while (j--) OUTPUT_BYTE(c);
  551.         i++;
  552.         count = 0;
  553.       }
  554.     }
  555.   }
  556.  
  557.   bzs->crc = crc;
  558.   if (bzs->lastblock && block[bzs->last] != 42)
  559.     bzs->err = XADERR_ILLEGALDATA;
  560. }
  561.  
  562.  
  563. static void bzip_MakeCRC32R(ULONG *buf, ULONG ID) {
  564.   ULONG k;
  565.   int i, j;
  566.   for(i = 0; i < 256; i++) {
  567.     k = i << 24;
  568.     for(j=8; j--;) k = (k & 0x80000000) ? ((k << 1) ^ ID) : (k << 1);
  569.     buf[i] = k;
  570.   }
  571. }
  572.  
  573. #define ERROR(error) do {bzs->err=XADERR_##error; goto exit_handler;} while(0)
  574. #define ALLOC(t,v,l) if (!((v) = (t) xadAllocVec((l),0))) ERROR(NOMEMORY)
  575. #define FREE(x) xadFreeObjectA((x), NULL)
  576.  
  577. ASM(LONG) SAVEDS bzip_UnArchive(REG(a0, struct xadArchiveInfo *ai), XADBASE) {
  578.   struct BZIPstate *bzs;
  579.   UBYTE sizechar;
  580.   LONG err;
  581.  
  582.   bzs = xadAllocVec(sizeof(struct BZIPstate), 0);
  583.   if (!bzs) { err = XADERR_NOMEMORY; goto exit_handler; }
  584.  
  585.   bzs->ai        = ai;
  586.   bzs->xad       = xadMasterBase;
  587.   bzs->crc       = ~0;
  588.   bzs->bitbuf    = 0;
  589.   bzs->bitsleft  = 0;
  590.   bzs->lastblock = 0;
  591.   bzs->err       = XADERR_OK;
  592.   bzs->block     = NULL;
  593.   bzs->ll        = NULL;
  594.   bzs->zptr      = NULL;
  595.   bzs->obufp     = bzs->outbuf;
  596.   bzs->obufend   = bzs->outbuf + BZIP_OUTBUF_SIZE;
  597.   bzs->bufp      = bzs->bufend = NULL;
  598.  
  599.   if ((bzs->err = xadHookAccess(XADAC_READ, 1, (APTR)&sizechar, ai)))
  600.     goto exit_handler;
  601.   if (sizechar < '1' || sizechar > '9') ERROR(DATAFORMAT);
  602.  
  603.   bzs->blocklen = 100000 * (sizechar - '0');
  604.   ALLOC(UBYTE *, bzs->block, bzs->blocklen * sizeof(UBYTE));
  605.   ALLOC(UBYTE *, bzs->ll,    bzs->blocklen * sizeof(UBYTE));
  606.   ALLOC(LONG *,  bzs->zptr,  bzs->blocklen * sizeof(LONG));
  607.  
  608.   bzip_MakeCRC32R(&bzip_crc32Table[0], 0x04C11DB7);
  609.   bzip_initBogusModel(bzs);
  610.   bzip_arithCodeStartDecoding(bzs);
  611.   do {
  612.     if (bzs->err) goto exit_handler; bzip_getAndMoveToFrontDecode(bzs);
  613.     if (bzs->err) goto exit_handler; bzip_undoReversibleTransformation(bzs);
  614.     if (bzs->err) goto exit_handler; bzip_spotBlock(bzs);
  615.     if (bzs->err) goto exit_handler; bzip_unRLEandDump(bzs);
  616.   } while (!bzs->lastblock);
  617.  
  618.   /* write any remaining bytes */
  619.   if (bzs->obufp > bzs->outbuf) {
  620.     if ((bzs->err = xadHookAccess(XADAC_WRITE, bzs->obufp - bzs->outbuf,
  621.       (APTR) bzs->outbuf, ai))) goto exit_handler;
  622.   }
  623.  
  624.   if ((!bzs->err) && (bzip_getULONG(bzs) != (~(bzs->crc)))) ERROR(CHECKSUM);
  625.  
  626. exit_handler:
  627.   if (bzs) {
  628.     err = bzs->err;
  629.     if (bzs->block) FREE(bzs->block);
  630.     if (bzs->ll)    FREE(bzs->ll);
  631.     if (bzs->zptr)  FREE(bzs->zptr);
  632.     FREE(bzs);
  633.   }
  634.   return err;
  635. }
  636.  
  637.  
  638. const struct xadClient bzip_Client = {
  639.   NEXTCLIENT, XADCLIENT_VERSION, 7, BZIP_VERSION, BZIP_REVISION,
  640.   4, XADCF_FILEARCHIVER | XADCF_FREEFILEINFO, 0, "BZip",
  641.   (BOOL (*)()) bzip_RecogData,
  642.   (LONG (*)()) bzip_GetInfo,
  643.   (LONG (*)()) bzip_UnArchive,
  644.   NULL
  645. };
  646.